<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us">
<head>
  <title>
    解决EasyUI DataGrid中的行在列冻结时无法对齐的问题 // 飞狐的部落格
  </title>

  <link href="http://gmpg.org/xfn/11" rel="profile">
<meta http-equiv="content-type" content="text/html; charset=utf-8">


<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">

<meta name="description" content="Blog of Rosen Lu">
<meta name="keywords" content="JavaScript,EasyUI,">
<meta name="author" content="飞狐">
<meta name="generator" content="Hugo 0.14" />

  <meta property="og:title" content="解决EasyUI DataGrid中的行在列冻结时无法对齐的问题" />
<meta property="og:description" content="Blog of Rosen Lu" />
<meta property="og:type" content="website" />
<meta property="og:locale" content="en_US" />
<meta property="og:url" content="http://lucumt.info/posts/easyui-datagrid-row-not-align-when-column-frozen/" />


  
   <link rel="stylesheet" href="http://lucumt.info/css/base-min.css">
   <link rel="stylesheet" href="http://lucumt.info/css/pure-min.css">
  
  
    <link rel="stylesheet" href="http://lucumt.info/css/grids-responsive-min.css">
  
  

  <link rel="stylesheet" href="http://lucumt.info/css/redlounge.css">
  
  <link rel="stylesheet" href="http://lucumt.info/css/googleapis.font.css">
  <link rel="stylesheet" href="http://lucumt.info/css/jqcloud.css">
  <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
  

  
  <link rel="apple-touch-icon-precomposed" sizes="144x144" href="http://lucumt.info/touch-icon-144-precomposed.png">
  <link rel="shortcut icon" href="http://lucumt.info/lucumt.ico">

  
  <link href="" rel="alternate" type="application/rss+xml" title="飞狐的部落格" />

  <script src="http://lucumt.info//js/jquery.min.js"></script>
  <script src="http://lucumt.info//js/jqcloud-1.0.4.min.js"></script>

    
  
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.6.0/styles/rainbow.min.css">
  
  <script src="http://lucumt.info/js/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script>


  

  

  

<script>
  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', "UA-75123653-1", 'auto');
  ga('send', 'pageview');
</script>




<script>
var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?cabc0a71f63da092412d82d1aefe7d1c";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();
</script>

</head>
<body>
	
		<div id="nav-to-top">
			<span class="decorative-marker">//</span><a href="#top">返回顶部</a>
		</div>
	

	<div id="layout" class="pure-g">
    
		 <a href="https://github.com/lucumt/ghblog" target="_new">
			<img style="position: absolute; top: 0; right: 0; border: 0;" 
			src="/img/forkme_right_red.png" alt="Fork me on GitHub">
		</a>

    <div class="sidebar pure-u-1 pure-u-md-1-4">
  <div class="header">
    

	
	  <img src="http://lucumt.info/img/photo.jpg" class="profilepic">
	

    <h1 class="brand-title">飞狐的部落格</h1>
    <h2 class="brand-tagline">Rosen Lu</h2>

    <nav class="nav">
      <ul class="nav-list">
        <li class="nav-item"><span class="nav-item-separator">//</span><a href="http://lucumt.info/">Home</a></li>
        
          <li class="nav-item"><span class="nav-item-separator">//</span><a href="http://lucumt.info/about/">About</a></li>
        
          <li class="nav-item"><span class="nav-item-separator">//</span><a href="http://lucumt.info/posts/">Blog</a></li>
        
      </ul>
    </nav>

    
    <div class="social-buttons">
      
        
        <a href="https://github.com/lucumt" target="_blank"><i class='fa fa-github'></i></a>
        
      
        
        <a href="https://plus.google.com/u/0/115794588502118898127/posts" target="_blank"><i class='fa fa-google-plus'></i></a>
        
      
        
        <a href="https://www.facebook.com/rosen.lu.1" target="_blank"><i class='fa fa-facebook'></i></a>
        
      
        
        <a href="http://www.twitter.com/rosenlucumt" target="_blank"><i class='fa fa-twitter'></i></a>
        
      
        
        <a href="mailto:lucumt@gmail.com" target="_blank"><i class='fa fa-mail-forward'></i></a>
        
      
    </div>
    
    
	
	  <hr class="nav-site-separator"/>
	  <nav class="nav">
      <ul class="nav-list">
	    
		   <li class="nav-site"><a href="http://lilydjwg.is-programmer.com/" target="_blank">依云的博客</a></li>
		
		   <li class="nav-site"><a href="http://evilbinary.org/" target="_blank">邪恶二进制</a></li>
		
		   <li class="nav-site"><a href="http://www.wlman.cc/" target="_blank">Consec &#39;s Blog</a></li>
		
		   <li class="nav-site"><a href="http://www.linuxzen.com/" target="_blank">cold&#39;s world</a></li>
		
		   <li class="nav-site"><a href="http://frantic1048.logdown.com/" target="_blank">Frantic log#1048</a></li>
		
	  </ul>
	  </nav>
	
	

  </div>
</div>

	
	

    <div class="content pure-u-1 pure-u-md-3-4">
		<a name="top"></a>
		

		
			
		    <div id="toc" class="pure-u-1 pure-u-md-1-4">
				<small class="toc-label">Contents</small>
		   	 	<nav id="TableOfContents">
<ul>
<li>
<ul>
<li><a href="#easyui-datagrid正常情况下的列冻结:1a1d88573c9d97df57840a524ba54e28">EasyUI DataGrid正常情况下的列冻结</a></li>
<li><a href="#easyui-datagrid非正常情形下的列冻结效果:1a1d88573c9d97df57840a524ba54e28">EasyUI DataGrid非正常情形下的列冻结效果</a></li>
<li><a href="#解决方案:1a1d88573c9d97df57840a524ba54e28">解决方案</a></li>
</ul></li>
</ul>
</nav>
		    </div>
		    
	    
  		<section class="post">
            <h1 class="post-title">
              <a href="http://lucumt.info/posts/easyui-datagrid-row-not-align-when-column-frozen">解决EasyUI DataGrid中的行在列冻结时无法对齐的问题</a>
            </h1>
            <h3 class="post-subtitle">
            	
            </h3>
            
            	<span class="post-date">
                	<span class="post-date-day"><sup>6</sup></span><span class="post-date-separator">/</span><span class="post-date-month">Aug</span> <span class="post-date-year">2017</span>
            	</span>
            	
            
            	
            		<span class="post-author-single">By <a class="post-author" href="https://www.linkedin.com/in/%E8%BF%90%E5%BC%BA-%E5%8D%A2-50a08bb5/" target="_new">飞狐</a></span>
            		




            	
            

			
			
				<div class="post-categories">
				
					<a class="post-category post-category-javascript" href="http://lucumt.info//categories/javascript">JavaScript</a>
				
					<a class="post-category post-category-easyui" href="http://lucumt.info//categories/easyui">EasyUI</a>
				
				</div>
			

			

			

            

<p>相对于传统的用HTML中TABLE实现的表格，利用 <strong><a href="https://www.jeasyui.com">EasyUI</a></strong> 中的 <strong><a href="https://www.jeasyui.com/demo/main/index.php?plugin=DataGrid">DataGrid</a></strong> 实现的表格具有很多优点，如可以 <em>对列宽进行拖动调整、列冻结、行冻结、自定义格式化</em> 等功能，故而在Web开发中得到了广泛的应用。最近自己在使用DataGrid的列冻结功能时遇到了由于某些单元格中的内容较多导致该行无法对齐的问题，由于当前在EasyUI官网中无法找到该问题的解决方案，自己研究DataGrid的实现原理后，找到了变通的解决方案，故先记录下。</p>

<h2 id="easyui-datagrid正常情况下的列冻结:1a1d88573c9d97df57840a524ba54e28">EasyUI DataGrid正常情况下的列冻结</h2>

<p>下图为一个常见的DataGrid使用示例，该图展示了我们在使用EasyUI DataGrid时经常会遇到的一个问题：<strong>由于某个列的长度很长导致表格出现滚动条</strong><br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-no-frozen-column1.png" alt="&quot;没有冻结列时正常显示的DataGrid&quot;" title="没有冻结列时正常显示的DataGrid" />
<br />
对应的代码为</p>

<pre><code>&lt;thead&gt;
   &lt;tr&gt;
     &lt;th data-options=&quot;field:'name'&quot;&gt;&lt;b&gt;书名&lt;/b&gt;&lt;/th&gt;
     &lt;th data-options=&quot;field:'price',align:'center',width:70&quot;&gt;&lt;b&gt;价格&lt;/b&gt;&lt;/th&gt;
     &lt;th data-options=&quot;field:'pubdate',align:'center',width:90&quot;&gt;&lt;b&gt;出版日期&lt;/b&gt;&lt;/th&gt;
     &lt;th data-options=&quot;field:'description',width:800&quot;&gt;&lt;b&gt;简要介绍&lt;/b&gt;&lt;/th&gt;
   &lt;/tr&gt;
&lt;/thead&gt;
</code></pre>

<p>得益于EasyUI DataGrid强大的功能，当表格中列的宽度太长时，它会自动加上横向滚动条，避免像传统的HTML TABLE表格在内容过多时会自己挤成一团，通过拖动滚动条，我们可以很方便的查看表格中各列的内容。</p>

<p>但有时候我们会运到另外一个问题，拖动滚动条时前面的某些列就不见了，如本例中的书名，在某些情况下可能会对我们的使用带来不便。<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-no-frozen-column2.png" alt="&quot;拖动滚动条时无法看见前面的列&quot;" title="拖动滚动条时无法看见前面的列" />
<br />
此时DataGrid的列冻结功能就可以派上用场了，只需要将需要固定的列冻结即可，在本例中我想把书名列冻结，在需要修改代码如下</p>

<pre><code> &lt;thead frozen=&quot;true&quot;&gt;
   &lt;tr&gt;
     &lt;th data-options=&quot;field:'name'&quot;&gt;&lt;b&gt;书名&lt;/b&gt;&lt;/th&gt;
   &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;thead&gt;
   &lt;tr&gt;
     &lt;th data-options=&quot;field:'price',align:'center',width:70&quot;&gt;&lt;b&gt;价格&lt;/b&gt;&lt;/th&gt;
     &lt;th data-options=&quot;field:'pubdate',align:'center',width:90&quot;&gt;&lt;b&gt;出版日期&lt;/b&gt;&lt;/th&gt;
     &lt;th data-options=&quot;field:'description',width:800&quot;&gt;&lt;b&gt;简要介绍&lt;/b&gt;&lt;/th&gt;
   &lt;/tr&gt;
 &lt;/thead&gt;
</code></pre>

<p>其对应的运行效果如下：<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-frozen-column1.png" alt="&quot;冻结列之后的DataGrid显示效果&quot;" title="冻结列之后的DataGrid显示效果" />
</p>

<h2 id="easyui-datagrid非正常情形下的列冻结效果:1a1d88573c9d97df57840a524ba54e28">EasyUI DataGrid非正常情形下的列冻结效果</h2>

<p>大多数情况下这种列冻结都能满足我们的需求，但上述冻结列正常显示有一个前提：<strong>表格中每一行各列的高度一致</strong>，若表格中某些行中存在列高超出DataGrid正常高度的情形(25px)，在进行列冻结时就会出现冻结行和非冻结行无法对齐的问题。</p>

<p>下图为一个列超出正常高度的DataGrid显示效果，从图中可以看出由于描述信息中的文字较多，导致正常的高度都比DataGrid默认的高度要很多，直观的显示就是不同行的高度不一致。<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-no-frozen-column3.png" alt="&quot;列高超出正常高度时的DataGrid&quot;" title="列高超出正常高度时的DataGrid" />
<br />
此时若对该表格进列冻结，同样会出现出现如前所述的冻结效果，但 <strong>如果我们在一开始就将描述信息这列隐藏掉，之后通过点击等方式让该列显示，则会出现冻结行和非冻结行无法对齐的情况</strong>，如下图所示<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-frozen-column-not-align-row.png" alt="&quot;列高超出正常高度时的DataGrid&quot;" title="列高超出正常高度时的DataGrid" />
<br />
对应的关键代码如下，也可以点击<a href="https://jsfiddle.net/wch9rnr2/8/">jsfiddle.net/wch9rnr2/8/</a>查看完整的代码</p>

<pre><code>&lt;button type=&quot;button&quot; onclick=&quot;toggleDescription()&quot;&gt;隐藏或显示描述信息&lt;/button&gt;
function toggleDescription(){
	var colOptions = $(&quot;#dg&quot;).datagrid(&quot;getColumnOption&quot;,&quot;description&quot;);
	var isHidden = !!colOptions.hidden;
  if(isHidden){
     $(&quot;#dg&quot;).datagrid(&quot;showColumn&quot;,&quot;description&quot;);
  }else{
     $(&quot;#dg&quot;).datagrid(&quot;hideColumn&quot;,&quot;description&quot;);
  }
}
</code></pre>

<p>从上图可以看出此时书名列和其余列已经无法对齐，严重印象了我们的使用效果。</p>

<h2 id="解决方案:1a1d88573c9d97df57840a524ba54e28">解决方案</h2>

<p>要想解决该问题，首先需要找出该问题产生的根源，利用Chrome或其它浏览器调试工具可知，当有部分列冻结时，DataGrid表格被分成了两个不同的表格，一个是冻结的表格，一个是未冻结的表格。进一步分析发现导致无法对齐的问题根源为 <strong>由于两个表格中同一行的高度不同，导致实际显示时看起来表格行没有对齐</strong>。<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-frozen-source-element.png" alt="&quot;DataGrid列冻结时的源代码&quot;" title="DataGrid列冻结时的源代码" />
<br />
找到问题根源后，要解决该问题，我们只需要让表格中每一行高度保持一致即可，具体来说就是 <strong>要在EasyUI DataGrid渲染表格之前将同一行的每一个单元格的高度保持一致即可</strong>。问题转化为寻找适当的方法切入点来修改单元格高度，即对单元格的高度进行校验。</p>

<p>为了修正单元格的高度，我们需要首先找出特定行已冻结单元格和未冻结单元格的高度，而要找出它们的高度必须要等EasyUI DataGrid渲染完毕之后才能获取到其实际高度。本列中由于点击按钮时会对最后一列进行隐藏或显示，所以我们可以在<code>toggleDescription</code>方法的最后执行相应的校验逻辑。</p>

<p>进一步调试分析后发现，对于DataGrid中的某一个数据行而言，冻结列的单元格高度都一样，非冻结列的单元格高度也一样，<strong>为了保持整行对齐，我们只需要高度较小的单元格的高度设置为高度较高的单元格的高度即可。考虑到有些影响列，同时为了简化实现，可以将及解决方案从设置单元格的高度更改为设置特定行在冻结和非冻结部分的行高即可</strong>。至于如何设置EasyUI DataGrid中数据行的高度，请参见EasyUI作者<strong>stworthy</strong>大神在<a href="http://www.jeasyui.com/forum/index.php?topic=4951.0">datagrid dynamically set / reset row height</a>中的回复，在该问题中，<strong>stworthy</strong>给出的解决方案如下：</p>

<pre><code>var dg = $('#dg');
dg.datagrid('options').rowHeight = 40;
for(var i=0; i&lt;dg.datagrid('getRows').length; i++){
    dg.datagrid('refreshRow', i);
}
</code></pre>

<p>基于此，我们可以将<code>toggleDescription</code>方法改进如下，完整的代码请参见<a href="https://jsfiddle.net/wch9rnr2/9/">jsfiddle.net/wch9rnr2/9/</a></p>

<pre><code>function toggleDescription(){
  var dg = $(&quot;#dg&quot;);
	var colOptions = dg.datagrid(&quot;getColumnOption&quot;,&quot;description&quot;);
	var isHidden = !!colOptions.hidden;
  if(isHidden){
     dg.datagrid(&quot;showColumn&quot;,&quot;description&quot;);
  }else{
     dg.datagrid(&quot;hideColumn&quot;,&quot;description&quot;);
  }
 
 var dgOptions = dg.datagrid(&quot;options&quot;);
 var rows = dg.datagrid(&quot;getRows&quot;);
 var row = null;
 var tr = null;
 var height1 =0;
 var height2 =0;
 for(var i in rows){
    row = rows[i];
	  tr = dgOptions.finder.getTr(dg[0],i);
	  height1 = $(tr[0]).height();//冻结行的高度
	  height2 = $(tr[1]).height();//非冻结行的高度
	  if((isHidden&amp;&amp;height2&gt;height1)||(!isHidden&amp;&amp;height1&gt;height2)){
         //冻结部分在显示时的高度取较大的那个
         $(tr[0]).css(&quot;height&quot;,height2+&quot;px&quot;);
	  }
	}
}
</code></pre>

<p>此时当我们点击按钮来显示描述信息时，DataGrid中的每一行都已经对齐，如下图所示，至此问题获得解决！<br />
<img src="http://lucumt.info/blog_img/easyui-datagrid-row-not-align-when-column-frozen/datagrid-frozen-column2.png" alt="&quot;重新校验后的DataGrid冻结列显示效果&quot;" title="重新校验后的DataGrid冻结列显示效果" />
</p>

<p>在实际使用中，我发现有时候上述JavaScript校验代码还是不能正常工作，其原因为在执行校验代码时，EasyUI DataGrid还没有完全渲染完毕，此时可以利用<strong><a href="https://www.w3schools.com/JSREF/met_win_setTimeout.asp">setTimeout</a></strong>函数来延后校验代码的执行，修改后的代码如下：</p>

<pre><code>function toggleDescription(){
  var dg = $(&quot;#dg&quot;);
	var colOptions = dg.datagrid(&quot;getColumnOption&quot;,&quot;description&quot;);
	var isHidden = !!colOptions.hidden;
  if(isHidden){
     dg.datagrid(&quot;showColumn&quot;,&quot;description&quot;);
  }else{
     dg.datagrid(&quot;hideColumn&quot;,&quot;description&quot;);
  }
 
 var dgOptions = dg.datagrid(&quot;options&quot;);
 var rows = dg.datagrid(&quot;getRows&quot;);
 var row = null;
 var tr = null;
 var height1 =0;
 var height2 =0;
 setTimeout(function(){
   for(var i in rows){
      row = rows[i];
      tr = dgOptions.finder.getTr(dg[0],i);
      height1 = $(tr[0]).height();//冻结行的高度
      height2 = $(tr[1]).height();//非冻结行的高度
      if((isHidden&amp;&amp;height2&gt;height1)||(!isHidden&amp;&amp;height1&gt;height2)){
           //冻结部分在显示时的高度取较大的那个
           $(tr[0]).css(&quot;height&quot;,height2+&quot;px&quot;);
      }
    } 
 },1000);//延后一秒执行
}
</code></pre>

<p>考虑到实际使用中EasyUI DataGrid的渲染时间无法确定，用<strong><a href="https://www.w3schools.com/JSREF/met_win_setTimeout.asp">setTimeout</a></strong>并非最优解，希望EasyUI官方后续能为该问题提供更合理的解决方案!</p>

	
			

			

			
          </section>
		  
		  <div class="page-link">
			
			<a href="http://lucumt.info/posts/java-concurrency/concurrency-models/">//下一篇</a>
			
			&nbsp;
			
			<a class="page-link-right" href="http://lucumt.info/posts/modify-java-class-file-content-directly/">//上一篇</a>
			
	      </div>

          
          	<div id="disqus_thread"></div>
<script type="text/javascript">
    var disqus_shortname = 'rosenlu';
    var disqus_identifier = 'http:\/\/lucumt.info\/posts\/easyui-datagrid-row-not-align-when-column-frozen\/';
    var disqus_title = '解决EasyUI DataGrid中的行在列冻结时无法对齐的问题';
    var disqus_url = 'http:\/\/lucumt.info\/posts\/easyui-datagrid-row-not-align-when-column-frozen\/';

    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>
          
        
      <div class="footer">
	<hr class="thin" />
	<div class="pure-menu pure-menu-horizontal pure-menu-open">
		<ul class="footer-menu">
		
			<li><a href="https://github.com/tmaiaroto/hugo-redlounge">Designed by Red Lounge</a></li>
		
		</ul>
	</div>

	<p>&copy; 2017. All rights reserved.</p>
</div>
    </div>
  </div>
	
		<script type="text/javascript">
			onscroll = function() {
			  var toTopVisible = false;
			  var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
			  if (scrollTop > 1000) {
			    if (!toTopVisible) {
			      document.getElementById('nav-to-top').style.display = 'block';
			    }
			  } else {
			    if (scrollTop < 1000 || toTopVisible) {
			      document.getElementById('nav-to-top').style.display = 'none';
			    }
			  }
			};
		</script>
	

	

  
</body>
</html>